package com.witframework.util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;

public class ExceptionUtils{
  public static String normalizeMessageChain(Exception e)  {
    return normalizeMessageChain(e, false);
  }

  public static String normalizeMessageChain(Exception e, boolean useHtmlBreak)  {
    String message = "";
    Throwable t = e;
    do{
      if (message.length() > 0) {
        message = message + ((useHtmlBreak) ? "<br>" : "\n");
        message = message + "Caused by: " + ((useHtmlBreak) ? "<br>" : "\n");
        message = message + "     " + t;
      } else {
        message = message + t; }
    }
    while ((t = t.getCause()) != null);

    if (useHtmlBreak)
      message = message.replaceAll("\n", "<br>");

    return message;
  }

  public static Throwable getRootCause(Throwable t_in) {
    Throwable t_out = t_in;

    while (t_out.getCause() != null)
      t_out = t_out.getCause();

    return t_out;
  }

  public static String getRootMessage(Throwable t){
    return getRootCause(t).toString();
  }

  public static String getRootLocalizedMessage(Throwable t){
    return getRootCause(t).toString();
  }

  public static Throwable getNormalizedCause(Throwable t){
    if (t.getCause() != null)
      return t.getCause();

    return t;
  }

  public static String getNormalizedMessage(Throwable t){
    if (t instanceof IllegalAccessException)
      return "IllegalAccessException: Can't access member due to visibility (non-public)";
    if (t instanceof InvocationTargetException)
      return getNormalizedCause(t).getMessage();
    if (t instanceof InstantiationException) {
      return "InstantiationException: Can't create new instance because of visibility (not public), or there's no suitable\nconstructor (might need an empty constructor), or it's an interface, or it's an abstract class";
    }

    return t.getMessage();
  }
  public static String formatStackTrace(Throwable t) {
      StringWriter sw = new StringWriter();
      try {
          PrintWriter p = new PrintWriter(sw);
          t.printStackTrace(p);
      } catch (Exception e) {
      }
      return sw.toString();
  }
  public static class WitCommonException extends Exception {
    private static final long serialVersionUID = 100L;

    public WitCommonException(Throwable cause) {
      super(ExceptionUtils.getNormalizedMessage(cause), cause);

      if (cause instanceof RuntimeException)
        throw ((RuntimeException)cause); 
    }

    public WitCommonException(String message) {
      super(message);
    }

    public WitCommonException(String message, Throwable cause) {
      super(ExceptionUtils.getNormalizedMessage(cause), cause);

      if (cause instanceof RuntimeException)
        throw ((RuntimeException)cause);
    }
  }
}
